package service

import (
	"errors"
	"fmt"

	"github.com/juexin/gin-base/internal/config"
	"github.com/juexin/gin-base/internal/model"
	"github.com/juexin/gin-base/pkg/jwt"
	"github.com/juexin/gin-base/pkg/utils"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
)

type AuthService struct {
	db         *gorm.DB
	cfg        *config.Config
	smsService *SMSService
}

func NewAuthService(db *gorm.DB, cfg *config.Config, smsService *SMSService) *AuthService {
	return &AuthService{
		db:         db,
		cfg:        cfg,
		smsService: smsService,
	}
}

// 请求结构体
type SetPasswordRequest struct {
	Password        string `json:"password" binding:"required,min=6,max=20"`
	ConfirmPassword string `json:"confirm_password" binding:"required"`
}

type LoginRequest struct {
	Phone       string `json:"phone" binding:"required"`
	Password    string `json:"password,omitempty"`
	Code        string `json:"code,omitempty"`
	LoginType   string `json:"login_type" binding:"required,oneof=password sms"`
	CaptchaID   string `json:"captcha_id,omitempty"`
	CaptchaCode string `json:"captcha_code,omitempty"`
}

// 响应结构体
type LoginResponse struct {
	Token string      `json:"token"`
	User  *model.User `json:"user"`
}

// SetPassword 设置密码
func (s *AuthService) SetPassword(userID uint, req *SetPasswordRequest) error {
	// 验证密码确认
	if req.Password != req.ConfirmPassword {
		return errors.New("两次输入的密码不一致")
	}

	// 查找用户
	var user model.User
	if err := s.db.First(&user, userID).Error; err != nil {
		return errors.New("用户不存在")
	}

	// 加密密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
	if err != nil {
		return errors.New("密码加密失败")
	}

	// 更新密码
	if err := s.db.Model(&user).Updates(map[string]interface{}{
		"password":     string(hashedPassword),
		"password_set": true,
	}).Error; err != nil {
		return errors.New("设置密码失败")
	}

	return nil
}

// Login 登录
func (s *AuthService) Login(req *LoginRequest) (*LoginResponse, error) {
	// 验证手机号格式
	if !utils.IsValidPhone(req.Phone) {
		return nil, errors.New("手机号格式不正确")
	}

	var user model.User
	err := s.db.Where("phone = ?", req.Phone).First(&user).Error

	if req.LoginType == "password" {
		// 密码登录
		if req.Password == "" {
			return nil, errors.New("密码不能为空")
		}

		if err != nil {
			if errors.Is(err, gorm.ErrRecordNotFound) {
				return nil, errors.New("用户不存在")
			}
			return nil, errors.New("登录失败")
		}

		// 验证密码
		if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password)); err != nil {
			return nil, errors.New("密码错误")
		}

	} else if req.LoginType == "sms" {
		// 短信验证码登录
		if req.Code == "" {
			return nil, errors.New("验证码不能为空")
		}

		// 验证短信验证码
		verifyReq := &VerifyCodeRequest{
			Phone:   req.Phone,
			Code:    req.Code,
			Purpose: "login",
		}
		if err := s.smsService.VerifyCode(verifyReq); err != nil {
			return nil, fmt.Errorf("验证码验证失败: %s", err.Error())
		}

		// 如果用户不存在，自动注册
		if err != nil {
			if errors.Is(err, gorm.ErrRecordNotFound) {
				user = model.User{
					Phone:    req.Phone,
					Nickname: "用户" + req.Phone[7:],
					Status:   1,
				}
				if err := s.db.Create(&user).Error; err != nil {
					return nil, errors.New("用户注册失败")
				}
			} else {
				return nil, errors.New("登录失败")
			}
		}
	} else {
		return nil, errors.New("不支持的登录方式")
	}

	// 检查用户状态
	if user.Status != 1 {
		return nil, errors.New("用户已被禁用")
	}

	// 生成JWT token
	token, err := jwt.GenerateToken(user.ID, user.Phone, s.cfg.JWT.Secret, s.cfg.JWT.ExpireHours)
	if err != nil {
		return nil, errors.New("生成token失败")
	}

	return &LoginResponse{
		Token: token,
		User:  &user,
	}, nil
}

// GetUserInfo 获取用户信息
func (s *AuthService) GetUserInfo(userID uint) (*model.User, error) {
	var user model.User
	if err := s.db.First(&user, userID).Error; err != nil {
		return nil, errors.New("用户不存在")
	}
	return &user, nil
}
